/*************************************************************************
    > File Name: DSA.h
    > Author: ZhaoLulu@BJTU
    > E-mail: 19281121@bjtu.edu.cn
    > Created Time: 2021年12月16日 星期四
 ************************************************************************/
#include "DSA.h"

gmp_randstate_t gmp_state;

void global_components(mpz_t &p, mpz_t &q, mpz_t &g) {
    gmp_randinit_default(gmp_state);
    gmp_randseed_ui(gmp_state, (unsigned int) (time(nullptr)));
    mpz_t tmp;
    mpz_t h;
    mpz_init(tmp);
    mpz_init(h);
    mpz_urandomb(q, gmp_state, 160);
    mpz_nextprime(q, q);
    while (true) {
        mpz_urandomb(tmp, gmp_state, 863);
        mpz_mul(p, tmp, q);
        mpz_add_ui(p, p, 1);
        if (mpz_probab_prime_p(p, 15) == 1) {
            break;
        }
    }
    mpz_urandomm(h, gmp_state, p);
    mpz_sub_ui(tmp, p, 1);
    mpz_cdiv_q(tmp, tmp, q);
    mpz_powm(g, h, tmp, p);
}

void private_key(mpz_t q, mpz_t &x) {
    mpz_urandomm(x, gmp_state, q);
}

void public_key(mpz_t g, mpz_t x, mpz_t p, mpz_t &y) {
    mpz_powm(y, g, x, p);
}

void secret_number(mpz_t q, mpz_t &k) {
    mpz_urandomm(k, gmp_state, q);
}

bool dsa_sign(mpz_t &r, mpz_t &s, mpz_t p, mpz_t q, mpz_t g, mpz_t k, mpz_t x, mpz_t HM) {
    mpz_t tmp;
    mpz_init(tmp);
    mpz_powm(r, g, k, p);
    mpz_mod(r, r, q);
    mpz_invert(tmp, k, q);
    mpz_mul(s, x, r);
    mpz_add(s, s, HM);
    mpz_mul(s, tmp, s);
    mpz_mod(s, s, q);
    return true;
}

bool dsa_verify(mpz_t r, mpz_t s, mpz_t p, mpz_t q, mpz_t g, mpz_t y, mpz_t HM) {
    mpz_t w, u1, u2, v, tmp;
    mpz_init(w);
    mpz_init(u1);
    mpz_init(u2);
    mpz_init(v);
    mpz_init(tmp);
    mpz_invert(w, s, q);
    mpz_mul(u1, HM, w);
    mpz_mod(u1, u1, q);
    mpz_mul(u2, r, w);
    mpz_mod(u2, u2, q);
    mpz_powm(tmp, g, u1, p);
    mpz_powm(v, y, u2, p);
    mpz_mul(v, tmp, v);
    mpz_mod(v, v, p);
    mpz_mod(v, v, q);
    gmp_printf("验证值：%Zd\n", v);
    if (mpz_cmp(v, r) == 0) {
        return true;
    } else {
        return false;
    }
}
